import React, { useState, useRef, useEffect } from 'react';
import './knowledgeGraph.css';
import Icon from '@/components/icon/Icon';

// 节点数据类型
interface NodeData {
    id: string;
    name: string;
    weight: number;
    x: number;
    y: number;
    isMain?: boolean;
    onClick?: () => void;
}

// 连接数据类型
interface ConnectionData {
    from: string;
    to: string;
}

// 关系图组件属性
interface RelationshipDiagramProps {
    nodes: NodeData[];
    connections: ConnectionData[];
    containerHeight?: number;
    containerWidth?: number;
}

const RelationshipDiagram: React.FC<RelationshipDiagramProps> = ({
                                                                     nodes,
                                                                     connections,
                                                                     containerHeight,
                                                                     containerWidth
                                                                 }) => {
    const [selectedNode, setSelectedNode] = useState<NodeData | null>(null);
    const [scale, setScale] = useState(1);
    const [position, setPosition] = useState({ x: 0, y: 0 });
    const [isDragging, setIsDragging] = useState(false);
    const [startDrag, setStartDrag] = useState({ x: 0, y: 0 });
    const diagramRef = useRef<HTMLDivElement>(null);
    const containerRef = useRef<HTMLDivElement>(null);
    const [isMobile, setIsMobile] = useState(false);
    const [, setDiagramSize] = useState({ width: 0, height: 0 });

    // 缩放范围调整
    const MIN_SCALE = 0.5;
    const MAX_SCALE = 2;

    // 检测屏幕尺寸
    useEffect(() => {
        const checkMobile = () => {
            setIsMobile(window.innerWidth < 768);
        };

        checkMobile();
        window.addEventListener('resize', checkMobile);
        return () => window.removeEventListener('resize', checkMobile);
    }, []);

    // 计算图谱尺寸和初始位置
    useEffect(() => {
        if (containerRef.current) {
            const { width, height } = containerRef.current.getBoundingClientRect();
            setDiagramSize({ width, height });

            // 计算初始居中位置
            const mainNode = nodes.find(n => n.isMain);
            if (mainNode) {
                // 计算主节点应该在容器中心的偏移量
                const centerX = width / 2 - mainNode.x - (mainNode.isMain ? 75 : 67.5);
                const centerY = height / 2 - mainNode.y - (mainNode.isMain ? 47.5 : 37.5);
                setPosition({ x: centerX, y: centerY });
            }
        }
    }, [nodes]);

    // 查找节点位置（计算中心点）
    const findNodePosition = (id: string) => {
        const node = nodes.find(n => n.id === id);
        if (!node) return { x: 0, y: 0 };

        const centerX = node.isMain ? node.x + 75 : node.x + 67.5;
        const centerY = node.isMain ? node.y + 47.5 : node.y + 37.5;
        return { x: centerX, y: centerY };
    };

    // 判断是否为主节点连接
    const isMainConnection = (nodeId: string) => {
        return nodes.find(n => n.id === nodeId)?.isMain;
    };

    // 处理开始拖动
    const handleStartDrag = (clientX: number, clientY: number) => {
        setIsDragging(true);
        setStartDrag({
            x: clientX - position.x,
            y: clientY - position.y
        });
    };

    // 鼠标按下事件
    const handleMouseDown = (e: React.MouseEvent) => {
        if (e.button !== 0) return;
        e.preventDefault();
        handleStartDrag(e.clientX, e.clientY);
    };

    // 触摸开始事件
    const handleTouchStart = (e: React.TouchEvent) => {
        if (e.touches.length !== 1) return;
        const touch = e.touches[0];
        e.preventDefault();
        handleStartDrag(touch.clientX, touch.clientY);
    };

    // 处理拖动
    const handleDragMove = (clientX: number, clientY: number) => {
        if (!isDragging) return;

        const newX = clientX - startDrag.x;
        const newY = clientY - startDrag.y;

        // 限制拖动范围
        if (containerRef.current) {
            const rect = containerRef.current.getBoundingClientRect();
            const maxOffset = 300; // 最大偏移量

            setPosition({
                x: Math.max(-maxOffset, Math.min(maxOffset, newX)),
                y: Math.max(-maxOffset, Math.min(maxOffset, newY))
            });
        } else {
            setPosition({ x: newX, y: newY });
        }
    };

    // 鼠标移动事件
    const handleMouseMove = (e: React.MouseEvent) => {
        handleDragMove(e.clientX, e.clientY);
    };

    // 触摸移动事件
    const handleTouchMove = (e: React.TouchEvent) => {
        if (e.touches.length !== 1 || !isDragging) return;
        const touch = e.touches[0];
        e.preventDefault();
        handleDragMove(touch.clientX, touch.clientY);
    };

    // 处理结束拖动
    const handleEndDrag = () => {
        setIsDragging(false);
    };

    // 鼠标释放事件
    const handleMouseUp = () => {
        handleEndDrag();
    };

    // 触摸结束事件
    const handleTouchEnd = () => {
        handleEndDrag();
    };

    // 处理滚轮缩放
    const handleWheel = (e: React.WheelEvent) => {
        e.preventDefault();

        if (!containerRef.current) return;

        const rect = containerRef.current.getBoundingClientRect();
        const mouseX = e.clientX - rect.left;
        const mouseY = e.clientY - rect.top;

        const mouseXBefore = (mouseX - position.x) / scale;
        const mouseYBefore = (mouseY - position.y) / scale;

        const delta = isMobile ? (e.deltaY < 0 ? 0.05 : -0.05) : (e.deltaY < 0 ? 0.1 : -0.1);
        const newScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale + delta));

        const newX = mouseX - mouseXBefore * newScale;
        const newY = mouseY - mouseYBefore * newScale;

        setScale(newScale);
        setPosition({ x: newX, y: newY });
    };

    // 重置视图
    const resetView = () => {
        // 重置时重新居中
        if (containerRef.current) {
            const { width, height } = containerRef.current.getBoundingClientRect();
            const mainNode = nodes.find(n => n.isMain);

            if (mainNode) {
                const centerX = width / 2 - mainNode.x - (mainNode.isMain ? 75 : 67.5);
                const centerY = height / 2 - mainNode.y - (mainNode.isMain ? 47.5 : 37.5);
                setPosition({ x: centerX, y: centerY });
            } else {
                setPosition({ x: width / 2, y: height / 2 });
            }
        }
        setScale(1);
    };

    // 双击放大
    const handleDoubleClick = (e: React.MouseEvent) => {
        e.preventDefault();

        if (!containerRef.current) return;

        const rect = containerRef.current.getBoundingClientRect();
        const mouseX = e.clientX - rect.left;
        const mouseY = e.clientY - rect.top;

        const mouseXBefore = (mouseX - position.x) / scale;
        const mouseYBefore = (mouseY - position.y) / scale;

        const scaleFactor = isMobile ? 1.3 : 1.5;
        const newScale = Math.min(MAX_SCALE, scale * scaleFactor);
        const newX = mouseX - mouseXBefore * newScale;
        const newY = mouseY - mouseYBefore * newScale;

        setScale(newScale);
        setPosition({ x: newX, y: newY });
    };

    // 绑定全局鼠标事件
    useEffect(() => {
        if (isDragging) {
            window.addEventListener('mousemove', handleMouseMove);
            window.addEventListener('mouseup', handleMouseUp);
            return () => {
                window.removeEventListener('mousemove', handleMouseMove);
                window.removeEventListener('mouseup', handleMouseUp);
            };
        }
    }, [isDragging, startDrag, position]);

    // 计算transform样式
    const getTransformStyle = () => {
        return {
            transform: `translate(${position.x}px, ${position.y}px) scale(${scale})`,
            transformOrigin: '0 0',
            transition: isDragging ? 'none' : 'transform 0.2s ease-out'
        };
    };

    // 计算容器尺寸
    const getContainerDimensions = () => {
        const width = containerWidth || '100%';
        const height = containerHeight || (isMobile ? '65vh' : '70vh');

        return { width, height };
    };

    return (
        <div
            ref={containerRef}
            className="diagram-wrapper"
            style={{
                ...getContainerDimensions(),
                overflow: 'hidden',
                position: 'relative',
                cursor: isDragging ? 'grabbing' : 'grab',
                borderRadius: '16px',
                margin: '0 auto',
            }}
            onMouseDown={handleMouseDown}
            onWheel={handleWheel}
            onDoubleClick={handleDoubleClick}
            onTouchStart={handleTouchStart}
            onTouchMove={handleTouchMove}
            onTouchEnd={handleTouchEnd}
            onTouchCancel={handleTouchEnd}
        >
            {/* 缩放控制按钮 */}
            <div className="diagram-controls" style={{
                top: isMobile ? '15px' : '20px',
                right: isMobile ? '15px' : '20px',
                gap: isMobile ? '8px' : '12px'
            }}>
                <button
                    className="control-btn zoom-in"
                    onClick={(e) => {
                        e.stopPropagation();
                        setScale(prev => Math.min(MAX_SCALE, prev * (isMobile ? 1.1 : 1.2)));
                    }}
                    aria-label="放大"
                >
                    <Icon icon={['fas', 'plus']} />
                </button>
                <button
                    className="control-btn zoom-out"
                    onClick={(e) => {
                        e.stopPropagation();
                        setScale(prev => Math.max(MIN_SCALE, prev / (isMobile ? 1.1 : 1.2)));
                    }}
                    aria-label="缩小"
                >
                    <Icon icon={['fas', 'minus']} />
                </button>
                <button
                    className="control-btn reset-view"
                    onClick={(e) => {
                        e.stopPropagation();
                        resetView();
                    }}
                    aria-label="重置视图"
                >
                    <Icon icon={['fas', 'home']} />
                </button>
            </div>

            <div
                ref={diagramRef}
                className="diagram-container"
                style={getTransformStyle()}
            >
                {/* 背景装饰层 */}
                <div className="diagram-bg-decoration" />

                {/* 连接线层 */}
                <svg
                    width="100%"
                    height="100%"
                    className="connector-svg"
                >
                    <defs>
                        {/* 箭头标记定义 */}
                        <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
                            <polygon points="0 0, 10 3.5, 0 7" className="arrow-fill" />
                        </marker>
                        <marker id="main-arrowhead" markerWidth="12" markerHeight="8" refX="11" refY="4" orient="auto">
                            <polygon points="0 0, 12 4, 0 8" className="main-arrow-fill" />
                        </marker>

                        {/* 粒子渐变定义 */}
                        <linearGradient id="particle-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
                            <stop offset="0%" stopColor="rgba(255,255,255,0.8)" />
                            <stop offset="100%" stopColor="rgba(255,255,255,0.2)" />
                        </linearGradient>
                    </defs>

                    {connections.map((conn, index) => {
                        const from = findNodePosition(conn.from);
                        const to = findNodePosition(conn.to);
                        const isMain = isMainConnection(conn.from);
                        // 改进曲线计算，使连接更自然
                        const distance = Math.sqrt(Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2));
                        const controlOffset = distance * 0.3; // 基于距离的控制点偏移
                        const controlX = (from.x + to.x) / 2;
                        const controlY = (from.y + to.y) / 2 - controlOffset;

                        const isRelatedToSelected = selectedNode
                            ? selectedNode.id === conn.from || selectedNode.id === conn.to
                            : false;

                        return (
                            <g key={index} className="connection-group">
                                {/* 曲线连接线 */}
                                <path
                                    className={`connector ${isMain ? 'main-connection' : ''} ${isRelatedToSelected ? 'highlight' : ''}`}
                                    d={`M ${from.x} ${from.y} Q ${controlX} ${controlY}, ${to.x} ${to.y}`}
                                    markerEnd={isMain ? 'url(#main-arrowhead)' : 'url(#arrowhead)'}
                                />

                                {/* 粒子流动动画（仅主连接） */}
                                {isMain && (
                                    <>
                                        <path
                                            id={`connection-path-${index}`}
                                            d={`M ${from.x} ${from.y} Q ${controlX} ${controlY}, ${to.x} ${to.y}`}
                                            fill="none"
                                            stroke="none"
                                        />
                                        <animateMotion
                                            href={`#connection-path-${index}`}
                                            dur={`${Math.max(2, distance / 150)}s`} // 基于距离的动画速度
                                            repeatCount="indefinite"
                                        >
                                            <circle r="3" fill="url(#particle-gradient)" className="connection-particle" />
                                        </animateMotion>
                                    </>
                                )}
                            </g>
                        );
                    })}
                </svg>

                {/* 节点层 */}
                {nodes.map((node, index) => (
                    <div
                        key={node.id}
                        className={`node-container ${selectedNode?.id === node.id ? 'selected' : ''}`}
                        style={{
                            left: node.x,
                            top: node.y,
                            zIndex: selectedNode?.id === node.id ? 10 : 2,
                            animation: `nodeEnter 0.5s ease-out ${0.1 * index}s forwards`
                        }}
                        onClick={(e) => {
                            e.stopPropagation();
                            setSelectedNode(prev => prev?.id === node.id ? null : node);
                            node.onClick?.();
                        }}
                    >
                        {node.isMain ? (
                            <div className="main-node">
                                <Icon icon={['fas', 'star']} className="main-icon" />
                                <span>{node.name}</span>
                            </div>
                        ) : (
                            <div className={`node ${node.weight ? 'weight-node' : ''}`}>
                                <Icon icon={['fas', 'book']} className="icon" />
                                <span>{node.name}</span>
                            </div>
                        )}
                    </div>
                ))}
            </div>
        </div>
    );
};

export default RelationshipDiagram;
